package heap

import "jvmgo/classfile"

type Field struct {
	slotId             uint
	constantValueIndex uint
	ClassMember
}

func (self *Field) SlotId() uint {
	return self.slotId
}
func (self *Field) Class() *Class {
	return self.class
}
func newFields(class *Class, cfFields []*classfile.MemberInfo) []*Field {
	fields := make([]*Field, len(cfFields))
	for i, cfFields := range cfFields {
		fields[i] = &Field{}
		fields[i].class = class
		fields[i].copyMemberInfo(cfFields)
		fields[i].copyAttributes(cfFields)
	}
	return fields
}

func (self *Field) copyAttributes(cfField *classfile.MemberInfo) {
	if valAttr := cfField.ConstantValueAttribute(); valAttr != nil {
		self.constantValueIndex = uint(valAttr.ConstantValueIndex())
	}
}

func (self *Field) IsLongOrDouble() bool {
	return self.descriptor == "J" || self.descriptor == "D"
}

func (self *Field) IsStatic() bool {
	return (self.accessFlags & ACC_STATIC) != 0
}

func (self *Field) IsFinal() bool {
	return (self.accessFlags & ACC_FINAL) != 0
}

func (self *Field) ConstantValueIndex() uint {
	return self.constantValueIndex
}

func (self *Field) Descriptor() string {
	return self.descriptor
}

// Is `value` can be accessed by `StringBuilder`
func (self *Field) isAccessibleTo(other *Class) bool {
	if self.IsPublic() {
		return true
	}
	class := self.class
	if self.IsProtected() {
		return class == other || other.isSubClassOf(class) || class.GetPackageName() == other.GetPackageName()
	}
	if !self.IsPrivate() {
		return class.GetPackageName() == other.GetPackageName()
	}
	return class == other

}

func (self *Field) Name() string {
	return self.name
}

func (self *Field) Type() *Class {
	className := toClassName(self.descriptor)
	return self.class.loader.LoadClass(className)
}

func (self *Field) AccessFlags() uint16 {
	return self.accessFlags
}
